package com.google.code.ojar.sendtemplatemail.app.msggenerators;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.code.ojar.sendtemplatemail.app.dto.Mail;
import com.google.code.ojar.sendtemplatemail.app.exception.AppException;
import com.google.code.ojar.sendtemplatemail.app.exception.EmailTemplateNotFound;
import com.google.code.ojar.sendtemplatemail.app.exception.MissingConfigurationException;
import com.google.code.ojar.sendtemplatemail.app.library.SendMailLibrary;
import com.google.code.ojar.sendtemplatemail.app.utils.SendMailUtils;

public abstract class MsgGenerator {

	// logger
	private static final Logger logger = LoggerFactory
			.getLogger(MsgGenerator.class);
	/**
	 * ADDR_SEPARATOR =",";
	 */
	protected static final String ADDR_SEPARATOR = ",";

	protected static final String TOKEN_INIT = "${";
	protected static final String TOKEN_END = "}";
	protected static final String TOKEN_REGEX_INIT = "\\$\\{";
	protected static final String TOKEN_REGEX_END = "\\}";
	protected String templatesFolder;
	protected String generatorName;
	
	
	public String getGeneratorName() {
		return generatorName;
	}

	public void setGeneratorName(String generatorName) {
		this.generatorName = generatorName;
	}

	protected Mail mailBean;

	/**
	 * method that generate a mail object
	 * 
	 * @param toAdds
	 *            String
	 * @param ccAddrs
	 *            String
	 * @param bccAdd
	 *            String
	 * @param args
	 * @return {@link Mail}
	 */
	public abstract Mail generateMailMsg(List<String> toAdds, List<String> ccAddrs,
			List<String> bccAdd, String[] args,Integer templateId) throws EmailTemplateNotFound,
			MissingConfigurationException;

	/**
	 * Constructor of the class
	 * 
	 * @throws MissingConfigurationException
	 */
	public MsgGenerator() {
		super();
	}

	/**
	 * method that returns a List with all the addresses defined in a coma
	 * separated list
	 * 
	 * @param addressList
	 *            String
	 * @return List<String>
	 */
	protected List<String> getListFromArray(String addressList) {

		List<String> list = null;
		if (addressList != null && !addressList.equals("")) {
			// verifico que sea una lista separada por comas
			int coma = addressList.indexOf(ADDR_SEPARATOR);
			if (coma > -1) {
				logger.debug("tiene coma");
				String[] addrs = addressList.split(ADDR_SEPARATOR);

				list = Arrays.asList(addrs);
				logger.debug("genero el array" + list.get(1));
			} else {
				list = new ArrayList<String>();
				list.add(addressList);
			}
		}
		return list;
	}

	/**
	 * 
	 * @param path
	 * @param fileName
	 * @return {@link String}
	 * @throws EmailTemplateNotFound
	 * 
	 */
	protected String getEmailTemplate(String path, String fileName)
			throws EmailTemplateNotFound {
		String content = null;
		String fileCompleteName = null;
		try {
			fileCompleteName = path + "/" + fileName;
			// obtengo el archivo
			File template = new File(fileCompleteName);
			FileInputStream fis = new FileInputStream(template);
			// obtengo el contenido en string
			content = IOUtils.toString(fis);

		} catch (FileNotFoundException e) {
			logger.error(EmailTemplateNotFound.TEMPLATE_NOT_FOUND
					+ fileCompleteName);
			throw new EmailTemplateNotFound(
					EmailTemplateNotFound.TEMPLATE_NOT_FOUND + fileCompleteName);
		} catch (IOException e) {
			logger.error(AppException.GENERIC_ERROR, e);
			throw new AppException(AppException.GENERIC_ERROR, e);
		}
		return content;
	}

	/**
	 * In charge of make the replacement of all currencies of a token in a
	 * content, the token in the content must have this syntax:
	 * <p>
	 * <b>${token}</b> example ${saludo}.<br>
	 * The token param <b><i>MUST NOT HAVE THE ${ , AND, }, JUST THE CONTENT
	 * </I></b> if the token is <i>${saludo}</i> send only <i>saludo</i>
	 * 
	 * @param content
	 *            String
	 * @param token
	 *            String
	 * @param replacement
	 *            String
	 * @return String
	 */
	protected String remplaceToken(String content, String token,
			String replacement) {
		final String regex = TOKEN_REGEX_INIT + token + TOKEN_REGEX_END;
		Pattern patt = Pattern.compile(regex);
		Matcher matcher = patt.matcher(content);
		if (matcher.find()) {
			content = matcher.replaceAll(replacement);
			logger.info("remplaced all ocurrences of : " + TOKEN_INIT + token
					+ TOKEN_END + " with: " + replacement);
		} else {
			logger.info("nothing to replace: " + TOKEN_INIT + token + TOKEN_END
					+ " with: " + replacement + " in: " + content);
		}
		return content;
	}

	/**
	 * Method that read the property file and search for the path to be use to
	 * retrieve the template
	 * 
	 * @throws MissingConfigurationException
	 *             if the path was not found
	 */
	public void setTemplateFolder() throws MissingConfigurationException {
		// verifico si el generador posee una carpeta propia
		logger.debug("custom folder:"
				+ SendMailLibrary.PROPERTY_GENERATORS_KEY_CUSTOM_FOLDER
				+ this.generatorName);
		String templateFolder = SendMailUtils.getPropertiesString(
				SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
				SendMailLibrary.PROPERTY_GENERATORS_KEY_CUSTOM_FOLDER
						+ this.generatorName);
		// verifico si esta establecido el por default
		if (templateFolder == null || templateFolder.equals("")) {
			templateFolder = SendMailUtils.getPropertiesString(
					SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
					SendMailLibrary.PROPERTY_GENERATORS_KEY_DEFAULT_FOLDER);
			if (templateFolder == null) {
				logger.error(MissingConfigurationException.MISSING_VALUE_TEMPLATE_FOLDER);
				throw new MissingConfigurationException(
						MissingConfigurationException.MISSING_VALUE_TEMPLATE_FOLDER);
			}
		}
		this.templatesFolder = templateFolder;
		logger.info("found template folder: " + this.templatesFolder
				+ " for generator: " + this.generatorName);
	}

	/**
	 * load a template, if a id is given, load an specific template defined in
	 * key <b>generator.template.file.{classname}.{id}</b>(multiple template
	 * behavior)<br>
	 * if templateId is null, load
	 * <b>generator.template.file.{classname}</b>(default template)
	 * 
	 * @param templateId
	 * 
	 * @return {@link String}
	 * @throws EmailTemplateNotFound
	 *             if the specified template is not found in the system
	 * @throws MissingConfigurationException
	 *             if no template name is defined
	 */
	protected String loadTemplate(Integer templateId)
			throws EmailTemplateNotFound, MissingConfigurationException {
		String template = "";
		String templateName = "";

		if (templateId == null) {
			templateName = SendMailUtils.getPropertiesString(
					SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
					SendMailLibrary.PROPERTY_GENERATORS_KEY_TEMPLATE_FILE
							+ this.generatorName);
			this.getEmailTemplate(this.templatesFolder, templateName);
		} else {
			templateName = SendMailUtils.getPropertiesString(
					SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
					SendMailLibrary.PROPERTY_GENERATORS_KEY_TEMPLATE_FILE
							+ this.generatorName + "."
							+ templateId);
		}
		if (templateName == null || templateName.equals("")) {
			logger.error(MissingConfigurationException.MISSING_VALUE_TEMPLATE_NAME);
			throw new MissingConfigurationException(
					MissingConfigurationException.MISSING_VALUE_TEMPLATE_NAME);
		}
		template = this.getEmailTemplate(this.templatesFolder, templateName);
		return template;
	}

	/**
	 * Gets the defined subject
	 * the subject must be defined in property file as follow:<b>
	 * no multiple templates: generator.template.subject.{generatorname}=value<br>
	 * multiple templates: generator.template.subject.{generatorname}.{number}=value</B>
	 * @param templateId
	 * @return String
	 */
	protected String loadSubject(Integer templateId) {
		String subject = null;

		if (templateId == null) {

			subject = SendMailUtils.getPropertiesString(
					SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
					SendMailLibrary.PROPERTY_GENERATORS_KEY_SUBJECT
							+ this.generatorName);

		} else {
			subject = SendMailUtils.getPropertiesString(
					SendMailLibrary.PROPERTY_GENERATORS_FILE_NAME,
					SendMailLibrary.PROPERTY_GENERATORS_KEY_SUBJECT
							+ this.generatorName + "."
							+ templateId);
		}
		if (subject == null || subject.equals("")) {
			logger.error("No subject was defined in property file...the mail will be send without subject");

		}

		return subject;
	}


}
